import React, { useState, useEffect } from "react";
// 声明全局类型，让 TypeScript 知道 window 对象上可能存在 SpeechRecognition 和 webkitSpeechRecognition 属性
declare global {
    interface Window {
        SpeechRecognition: any;
        webkitSpeechRecognition: any;
    }
}
// 定义 VoiceAssistant 函数组件，用于创建语音助手界面
const VoiceAssistant: React.FC = () => {
    // 使用 useState 钩子来管理组件的状态
    // isListening 表示语音识别是否正在监听用户输入
    const [isListening, setIsListening] = useState<boolean>(false);
    // recognizedText 存储语音识别到的文本内容
    const [recognizedText, setRecognizedText] = useState<string>("");
    // responseText 存储语音助手的回复文本
    const [responseText, setResponseText] = useState<string>("");
    // isSpeaking 表示语音助手是否正在进行语音回复
    const [isSpeaking, setIsSpeaking] = useState<boolean>(false);
    // barrages 是一个字符串数组，用于存储要显示的弹幕内容
    const [barrages, setBarrages] = useState<string[]>([]);

    // 使用 useEffect 钩子来处理副作用，这里主要处理语音识别相关逻辑
    useEffect(() => {
        // 检查浏览器是否支持语音识别功能
        if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) {
            // 如果不支持，弹出提示框告知用户
            alert("您的浏览器不支持语音识别功能");
            return;
        }

        // 检查浏览器是否支持语音合成功能
        if (!('speechSynthesis' in window)) {
            // 如果不支持，弹出提示框告知用户
            alert("您的浏览器不支持语音合成功能");
            return;
        }

        // 获取浏览器支持的语音识别构造函数
        const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
        // 创建语音识别实例
        const recognition = new SpeechRecognition();

        // 配置语音识别的相关参数
        // continuous 设为 true 表示持续识别，直到手动停止
        recognition.continuous = true;
        // interimResults 设为 true 表示返回临时识别结果
        recognition.interimResults = true;
        // 设置识别语言为中文
        recognition.lang = "zh-CN";
        // 设置最多返回 1 个识别结果
        recognition.maxAlternatives = 1;

        // 当语音识别开始时触发的回调函数
        recognition.onstart = () => {
            console.log("语音识别已启动");
            // 更新 isListening 状态为 true
            setIsListening(true);
        };

        // 当语音识别停止时触发的回调函数
        recognition.onend = () => {
            console.log("语音识别已停止");
            // 如果 isListening 仍然为 true，尝试重新启动语音识别
            if (isListening) {
                try {
                    recognition.start();
                } catch (error) {
                    // 若重新启动失败，打印错误信息
                    console.error('重新启动语音识别失败:', error);
                }
            }
        };

        // 当语音识别有结果时触发的回调函数
        recognition.onresult = (event: SpeechRecognitionEvent) => {
            let interimTranscript = ""; // 存储临时识别结果
            let finalTranscript = ""; // 存储最终识别结果

            try {
                // 遍历识别结果数组
                for (let i = event.resultIndex; i < event.results.length; i++) {
                    const transcript = event.results[i][0].transcript.trim();
                    if (event.results[i].isFinal) {
                        // 如果是最终结果，添加到 finalTranscript 中
                        finalTranscript += transcript + " ";
                    } else {
                        // 如果是临时结果，添加到 interimTranscript 中
                        interimTranscript += transcript;
                    }
                }

                // 获取当前的识别文本，优先使用最终结果
                const currentText = finalTranscript || interimTranscript;
                // 更新 recognizedText 状态
                setRecognizedText(currentText);

                // 只有当有最终结果时才处理命令
                if (finalTranscript) {
                    // 调用 handleCommand 函数处理命令
                    handleCommand(finalTranscript.toLowerCase());
                }
            } catch (error) {
                // 若处理识别结果出错，打印错误信息
                console.error('处理语音识别结果时出错:', error);
            }
        };

        // 当语音识别出错时触发的回调函数
        recognition.onerror = (event: SpeechRecognitionErrorEvent) => {
            console.error("语音识别错误:", event.error);
            if (event.error === 'network') {
                // 如果是网络错误，弹出提示框让用户检查网络
                alert("网络连接出错，请检查网络后重试");
            } else if (event.error === 'not-allowed') {
                // 如果是权限问题，弹出提示框让用户允许使用麦克风权限
                alert("请允许使用麦克风权限");
            } else {
                // 其他错误，弹出提示框告知具体错误信息
                alert(`语音识别出错: ${event.error}`);
            }
            // 更新 isListening 状态为 false
            setIsListening(false);
        };

        // 用于存储定时器 ID，以便后续清除定时器
        let recognitionTimeout: NodeJS.Timeout;
        if (isListening) {
            try {
                // 启动语音识别
                recognition.start();
                // 设置一个 10 秒的定时器，定时重启语音识别
                recognitionTimeout = setTimeout(() => {
                    recognition.stop();
                    recognition.start();
                }, 10000);
            } catch (error) {
                // 若启动语音识别出错，打印错误信息
                console.error('启动语音识别时出错:', error);
            }
        } else {
            // 如果 isListening 为 false，停止语音识别
            recognition.stop();
        }

        // 组件卸载时的清理函数
        return () => {
            // 清除定时器
            clearTimeout(recognitionTimeout);
            // 停止语音识别
            recognition.stop();
        };
    }, [isListening]);

    // 处理用户语音命令的函数
    const handleCommand = (text: string) => {
        // 定义预设的命令和对应的回复
        const commands = {
            "小维": "我在呢",
            "你叫什么": "我叫小维",
            "八维有哪些专业": "网站工程，人工智能，物联网，网络工程、全栈开发、游戏设计、元宇宙、云计算、大数据",
            "你知道八维吗": "八维是中国领先的职业教育培训机构",
            "你家在哪": "北京昌平",
            "你好": "你好，我是小维，很高兴见到你",
            "再见": "再见，欢迎下次再来找我聊天"
        };

        // 遍历预设的命令
        for (const [keyword, response] of Object.entries(commands)) {
            if (text.includes(keyword)) {
                // 如果用户输入的文本包含预设的关键词，调用 respondToCommand 函数进行回复
                respondToCommand(response);
                break;
            }
        }
    };

    // 处理语音助手回复的函数
    const respondToCommand = (response: string) => {
        // 更新 responseText 状态
        setResponseText(response);

        // 取消之前正在进行的语音合成
        window.speechSynthesis.cancel();

        // 创建语音合成实例
        const speech = new SpeechSynthesisUtterance(response);
        // 设置语音合成的语言为中文
        speech.lang = "zh-CN";
        // 设置语速
        speech.rate = 1.0;
        // 设置音高
        speech.pitch = 1.0;
        // 设置音量
        speech.volume = 1.0;

        // 当语音合成开始时触发的回调函数
        speech.onstart = () => {
            // 更新 isSpeaking 状态为 true
            setIsSpeaking(true);
        };

        // 当语音合成结束时触发的回调函数
        speech.onend = () => {
            // 更新 isSpeaking 状态为 false
            setIsSpeaking(false);
        };

        // 当语音合成出错时触发的回调函数
        speech.onerror = (event) => {
            // 打印错误信息
            console.error('语音合成错误:', event);
            // 更新 isSpeaking 状态为 false
            setIsSpeaking(false);
        };

        // 开始语音合成
        window.speechSynthesis.speak(speech);
        // 将回复内容添加到弹幕列表中
        setBarrages(prevBarrages => [...prevBarrages, response]);
    };

    // 切换语音识别监听状态的函数
    const toggleListening = () => {
        // 取反 isListening 状态
        setIsListening(prev => !prev);
    };

    // 返回组件的 JSX 结构
    return (
        <div className="voice-assistant" style={{
            padding: "20px",
            maxWidth: "600px",
            margin: "0 auto",
            textAlign: "center"
        }}>
            <h2>语音助手</h2>
            <button
                onClick={toggleListening}
                style={{
                    padding: "12px 24px",
                    fontSize: "16px",
                    borderRadius: "8px",
                    backgroundColor: isListening ? "#ff4444" : "#4CAF50",
                    color: "white",
                    border: "none",
                    cursor: "pointer",
                    marginBottom: "20px"
                }}
            >
                {/* 根据 isListening 状态显示不同的按钮文本 */}
                {isListening ? "停止识别" : "开始识别"}
            </button>

            <div style={{
                padding: "15px",
                marginBottom: "15px",
                border: "1px solid #ddd",
                borderRadius: "8px",
                backgroundColor: "#f9f9f9"
            }}>
                <h3>识别结果:</h3>
                {/* 显示识别到的文本，如果没有则显示提示信息 */}
                <p>{recognizedText || "等待说话..."}</p>
            </div>

            <div style={{
                padding: "15px",
                border: "1px solid #ddd",
                borderRadius: "8px",
                backgroundColor: "#f0f8ff"
            }}>
                <h3>助手回复:</h3>
                {/* 显示助手的回复文本，如果没有则显示提示信息 */}
                <p>{responseText || "等待命令..."}</p>
                {/* 如果正在说话，显示提示信息 */}
                {isSpeaking && <p style={{ color: "#666" }}>正在播放语音...</p>}
            </div>

            {/* 弹幕容器 */}
            <div className="barrage-container" style={{
                position: "relative",
                height: "100px",
                overflow: "hidden",
                marginTop: "20px"
            }}>
                {/* 遍历弹幕列表，渲染每个弹幕 */}
                {barrages.map((barrage, index) => (
                    <div
                        key={index}
                        className="barrage"
                        style={{
                            position: "absolute",
                            top: `${Math.floor(Math.random() * 80)}px`,
                            left: "100%",
                            animation: `barrageAnimation 10s linear infinite`,
                            backgroundColor: "rgba(0, 0, 0, 0.7)",
                            color: "white",
                            padding: "5px 10px",
                            borderRadius: "5px",
                            whiteSpace: "nowrap"
                        }}
                    >
                        {barrage}
                    </div>
                ))}
            </div>
        </div>
    );
};

// 创建一个 style 元素，用于定义 CSS 动画
const style = document.createElement('style');
style.innerHTML = `
    @keyframes barrageAnimation {
        from {
            left: 100%;
        }
        to {
            left: -100%;
        }
    }
`;
// 将 style 元素添加到文档的 head 中
document.head.appendChild(style);

// 导出 VoiceAssistant 组件
export default VoiceAssistant;